/**
 * @p.md
 * 
 * Middleware 模块，提供消息拦截和处理中间件功能
 */
import { Context } from './context';
import { PID } from './pid';

/**
 * 中间件接口，定义消息处理拦截点
 */
export interface Middleware {
  /**
   * 拦截发送消息
   * @param context 上下文
   * @param target 目标 PID
   * @param envelope 消息信封
   * @param next 下一个中间件
   */
  onSend(context: Context, target: PID, envelope: any, next: (context: Context, target: PID, envelope: any) => void): void;
  
  /**
   * 拦截接收消息
   * @param context 上下文
   * @param envelope 消息信封
   * @param next 下一个中间件
   */
  onReceive(context: Context, envelope: any, next: (context: Context, envelope: any) => void): void;
}

/**
 * 中间件工厂函数类型
 */
export type MiddlewareFactory = () => Middleware;

/**
 * 消息信封，包含消息和元数据
 */
export interface MessageEnvelope {
  /**
   * 消息内容
   */
  message: any;
  
  /**
   * 发送者 PID
   */
  sender?: PID;
  
  /**
   * 消息头信息
   */
  header?: Map<string, string>;
}

/**
 * 创建消息信封
 * @param message 消息内容
 * @param sender 发送者 PID
 * @param header 消息头信息
 */
export function createMessageEnvelope(message: any, sender?: PID, header?: Map<string, string>): MessageEnvelope {
  return { message, sender, header };
}

/**
 * 日志中间件，记录消息发送和接收
 */
export class LoggingMiddleware implements Middleware {
  private readonly name: string;
  
  /**
   * 创建日志中间件
   * @param name 中间件名称，用于标识日志来源
   */
  constructor(name: string = 'logging') {
    this.name = name;
  }
  
  /**
   * 拦截发送消息，记录日志
   */
  onSend(context: Context, target: PID, envelope: any, next: (context: Context, target: PID, envelope: any) => void): void {
    console.log(`[${this.name}] Sending message to ${target.address}/${target.id}:`, envelope);
    next(context, target, envelope);
  }
  
  /**
   * 拦截接收消息，记录日志
   */
  onReceive(context: Context, envelope: any, next: (context: Context, envelope: any) => void): void {
    console.log(`[${this.name}] Receiving message:`, envelope);
    next(context, envelope);
  }
}

/**
 * 超时中间件，为消息添加超时处理
 */
export class TimeoutMiddleware implements Middleware {
  private readonly timeout: number;
  
  /**
   * 创建超时中间件
   * @param timeout 超时时间（毫秒），默认为5000
   */
  constructor(timeout: number = 5000) {
    this.timeout = timeout;
  }
  
  /**
   * 拦截发送消息，添加超时检查
   */
  onSend(context: Context, target: PID, envelope: any, next: (context: Context, target: PID, envelope: any) => void): void {
    // 创建超时处理
    const timeoutId = setTimeout(() => {
      console.warn(`[TimeoutMiddleware] Message to ${target.address}/${target.id} timed out after ${this.timeout}ms`);
      // 在实际实现中，这里应该处理超时，例如通知发送方
    }, this.timeout);
    
    // 添加超时取消函数到消息头
    const header = envelope.header || new Map<string, string>();
    header.set('timeout-id', timeoutId.toString());
    
    // 包装消息
    const wrappedEnvelope = {
      ...envelope,
      header
    };
    
    next(context, target, wrappedEnvelope);
  }
  
  /**
   * 拦截接收消息，取消超时
   */
  onReceive(context: Context, envelope: any, next: (context: Context, envelope: any) => void): void {
    // 如果有超时 ID，取消超时
    if (envelope.header && envelope.header.has('timeout-id')) {
      const timeoutId = parseInt(envelope.header.get('timeout-id') || '0');
      if (timeoutId) {
        clearTimeout(timeoutId);
      }
    }
    
    next(context, envelope);
  }
}

/**
 * 重试中间件，自动重试失败的消息发送
 */
export class RetryMiddleware implements Middleware {
  private readonly maxRetries: number;
  private readonly retryDelay: number;
  
  /**
   * 创建重试中间件
   * @param maxRetries 最大重试次数，默认为3
   * @param retryDelay 重试延迟（毫秒），默认为1000
   */
  constructor(maxRetries: number = 3, retryDelay: number = 1000) {
    this.maxRetries = maxRetries;
    this.retryDelay = retryDelay;
  }
  
  /**
   * 拦截发送消息，添加重试功能
   */
  onSend(context: Context, target: PID, envelope: any, next: (context: Context, target: PID, envelope: any) => void): void {
    // 获取当前重试次数
    const header = envelope.header || new Map<string, string>();
    const retryCount = parseInt(header.get('retry-count') || '0');
    
    // 尝试发送
    try {
      next(context, target, {
        ...envelope,
        header: header.set('retry-count', retryCount.toString())
      });
    } catch (error) {
      // 处理错误，如果未超过最大重试次数，则重试
      if (retryCount < this.maxRetries) {
        console.warn(`[RetryMiddleware] Retrying message to ${target.address}/${target.id}, attempt ${retryCount + 1}/${this.maxRetries}`);
        
        // 延迟重试
        setTimeout(() => {
          this.onSend(context, target, {
            ...envelope,
            header: header.set('retry-count', (retryCount + 1).toString())
          }, next);
        }, this.retryDelay);
      } else {
        console.error(`[RetryMiddleware] Failed to send message after ${this.maxRetries} attempts:`, error);
        throw error;
      }
    }
  }
  
  /**
   * 拦截接收消息
   */
  onReceive(context: Context, envelope: any, next: (context: Context, envelope: any) => void): void {
    next(context, envelope);
  }
}

/**
 * 中间件工厂，提供常用中间件的创建函数
 */
export const Middlewares = {
  /**
   * 创建日志中间件
   * @param name 中间件名称
   */
  logging(name?: string): Middleware {
    return new LoggingMiddleware(name);
  },
  
  /**
   * 创建超时中间件
   * @param timeout 超时时间（毫秒）
   */
  timeout(timeout?: number): Middleware {
    return new TimeoutMiddleware(timeout);
  },
  
  /**
   * 创建重试中间件
   * @param maxRetries 最大重试次数
   * @param retryDelay 重试延迟（毫秒）
   */
  retry(maxRetries?: number, retryDelay?: number): Middleware {
    return new RetryMiddleware(maxRetries, retryDelay);
  }
}; 